home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 12 - 1996 / 12.11 Nov 96 / DebuggingStarter Code / DebugLeaks.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-05  |  11.9 KB  |  386 lines  |  [TEXT/CWIE]

  1. /*________________________________________________________________________________
  2.     DebugLeaks.c:  leaks tracking code.
  3.  
  4.     Note:
  5.         The routines provided here are only shells to guide you in implementing leaks
  6.     code. No implementation is provided.  However, suggested data structures are
  7.     shown.
  8. ________________________________________________________________________________*/
  9.  
  10. #include "DebugLeaks.h"
  11. #include "DebugTrapsOff.h"
  12.  
  13.  
  14. #if USE_DEBUG_LEAKS    // [
  15.  
  16.  
  17. /*________________________________________________________________________________
  18.     Suggested struct to remember an item.
  19. ________________________________________________________________________________*/
  20. typedef struct RememberedItem
  21.     {
  22.     const void                *itemMemory;    // Ptr, Handle, or object pointer
  23.     
  24.     // if it's an object, the file name isn't useful, since allocation always occurs
  25.     // in operator new. So store the object size instead, since we cannot obtain that later.
  26.     #define kMaxObjectSize        ( 65535 )    // max size we can remember in 'objectSize' field
  27.     union
  28.         {
  29.         UInt16                fileNameIndex;    // index into a string list
  30.         UInt16                objectSize;        // if an object
  31.         } info;
  32.     
  33.     DebugLeaksHowAllocated    howAllocated;
  34.     
  35.     UInt8        notReallyALeak             : 1;    // used to ignore known leaks
  36.     UInt8        objectSizeMoreThanMax    : 1;    // if an object: it's size exceeds kMaxObjectSize
  37.     UInt8        addedWhileSuspended     : 1;    // used to ignore items we want to ignore
  38.     UInt8        unused                     : 5;
  39.     } RememberedItem;
  40.     
  41. #define ItemFileNameIndex( i )    ( (i)->info.fileNameIndex )
  42. #define ItemObjectSize( i )        ( (i)->info.objectSize )
  43. #define ItemIsObject( i )        ( (i)->howAllocated == kSDL_OperatorNew )
  44.  
  45.  
  46.  
  47. /*________________________________________________________________________________
  48.     Suggested struct for a Leaks session.
  49.     
  50.     Contains an array of RememberItems and associated information
  51. ________________________________________________________________________________*/
  52. typedef struct LeaksSession
  53.     {
  54.     Str32            sessionName;
  55.     
  56.     UInt32            maxItems;        // e.g. items = NewHandle( maxItems * sizeof( **items ) );
  57.     RememberedItem    **items;        // Handle to array of RememberedItems
  58.     UInt32            numActiveItems;    // how many are actually in use right now [0, numActiveItems -1]
  59.     
  60.     // counts how many of each are allocated; increases only
  61.     // could be useful for analyzing program memory allocations
  62.     UInt32            numHandles;
  63.     UInt32            numPtrs;
  64.     UInt32            numObjects;
  65.     } LeaksSession;
  66.  
  67.  
  68.  
  69. /*________________________________________________________________________________
  70.     Suggested struct for keeping a list of file names
  71. ________________________________________________________________________________*/
  72. typedef struct StringList
  73.     {
  74.     UInt16            numStrings;
  75.     unsigned char    strings[];    // packed array of pascal strings follows, just like a STR#
  76.     } StringList, **StringListHandle;
  77.  
  78.  
  79. /*________________________________________________________________________________
  80.     Suggested struct for the Leaks manager.
  81.     
  82.     Remembers all sessions as a stack; top one is current session.
  83. ________________________________________________________________________________*/
  84. typedef struct SessionList
  85.     {
  86.     UInt16                numSessions;    // how many sessions currently exist
  87.     UInt16                maxSessions;    // maximum number of sessions possible
  88.     
  89.     UInt16                suspendCount;    // to track suspend/resume pairing
  90.     
  91.     #define kDefaultNameStrIndex        1    // we add one default string when we create it
  92.     StringListHandle    fileNameList;
  93.     
  94.     LeaksSession        sessionsArray[ ];    // dynamically allocate as many as desired
  95.     } SessionList;
  96.  
  97.  
  98.  
  99.  
  100. /*————————————————————————————————————————————————————————————————————————————————————————
  101.     Note:
  102.         Some of the routines in this file would normally be called only from DebugTraps,
  103.     usually not from general program code.
  104. ————————————————————————————————————————————————————————————————————————————————————————*/
  105.  
  106. #if PRAGMA_MARK_SUPPORTED
  107. #pragma mark --- Rare Public Use ---
  108. #endif
  109.  
  110.  
  111. /*————————————————————————————————————————————————————————————————————————————————————————
  112.     Remember a Ptr or Handle.
  113.     
  114.     Use the next available slot in the list.
  115.     
  116.     Note: A RememberedItem may need to initialized slightly differently for an object
  117.     so handle that in DebugLeaks_RememberObject, not here.
  118. ————————————————————————————————————————————————————————————————————————————————————————*/
  119.     static void
  120. RememberHandleOrPtr(
  121.     const void *            theItem,
  122.     DebugLeaksHowAllocated    howAllocated,
  123.     const char *            srcFileNameCString)
  124.     {
  125.     }
  126.     
  127.     
  128.  
  129. /*————————————————————————————————————————————————————————————————————————————————————————
  130.     Forget an item; it has been disposed of properly.
  131.     
  132.     Copy the last in-use item to its place to keep the list compact.
  133. ————————————————————————————————————————————————————————————————————————————————————————*/
  134.     static void
  135. ForgetItem( const void    *handleOrPtr)
  136.     {
  137.     }
  138.     
  139.     
  140. /*————————————————————————————————————————————————————————————————————————————————————————
  141.     A Handle has been allocated. Remember it.
  142. ————————————————————————————————————————————————————————————————————————————————————————*/
  143.     void
  144. DebugLeaks_RememberHandle(
  145.     Handle                    theHandle,
  146.     DebugLeaksHowAllocated    howAllocated,
  147.     const char *            srcFileNameCString)
  148.     {
  149.     RememberHandleOrPtr( theHandle, howAllocated, srcFileNameCString);
  150.     }
  151.  
  152.  
  153.  
  154. /*————————————————————————————————————————————————————————————————————————————————————————
  155.     A Handle has been deallocated. Forget it.
  156. ————————————————————————————————————————————————————————————————————————————————————————*/
  157.     void
  158. DebugLeaks_ForgetHandle( Handle    theHandle)
  159.     {
  160.     ForgetItem( theHandle );
  161.     }
  162.  
  163.  
  164.  
  165. /*————————————————————————————————————————————————————————————————————————————————————————
  166.     A memory manager 'Ptr' has been allocated. Remember it.
  167. ————————————————————————————————————————————————————————————————————————————————————————*/
  168.     void
  169. DebugLeaks_RememberPtr(
  170.     void *                    thePtr,
  171.     DebugLeaksHowAllocated    howAllocated,
  172.     const char *            srcFileNameCString)
  173.     {
  174.     RememberHandleOrPtr( thePtr, howAllocated, srcFileNameCString);
  175.     }
  176.  
  177.  
  178. /*————————————————————————————————————————————————————————————————————————————————————————
  179.     A Ptr has been deallocated. Forget it.
  180. ————————————————————————————————————————————————————————————————————————————————————————*/
  181.     void
  182. DebugLeaks_ForgetPtr( void    *thePtr)
  183.     {
  184.     ForgetItem( thePtr );
  185.     }
  186.  
  187.  
  188.  
  189. /*————————————————————————————————————————————————————————————————————————————————————————
  190.     A AEDesc has been allocated. Remember it.
  191. ————————————————————————————————————————————————————————————————————————————————————————*/
  192.     void
  193. DebugLeaks_RememberAEDesc(
  194.     AEDesc *                theAEDesc,
  195.     DebugLeaksHowAllocated    howAllocated,
  196.     const char *            srcFileNameCString)
  197.     {
  198.     AssertAddressIsValidAlign2( theAEDesc, "\pDebugLeaks_RememberAEDesc");
  199.  
  200.     if ( theAEDesc->descriptorType != typeNull &&
  201.          IsntNil( theAEDesc->dataHandle ))
  202.         {
  203.         RememberHandleOrPtr( theAEDesc->dataHandle, howAllocated, srcFileNameCString);
  204.         }
  205.     }
  206.  
  207.  
  208.  
  209. /*————————————————————————————————————————————————————————————————————————————————————————
  210.     A AEDesc has been deallocated. Forget it.
  211. ————————————————————————————————————————————————————————————————————————————————————————*/
  212.     void
  213. DebugLeaks_ForgetAEDesc( AEDesc    *theAEDesc)
  214.     {
  215.     AssertAddressIsValidAlign2( theAEDesc, "\pDebugLeaks_ForgetAEDesc");
  216.  
  217.     if ( theAEDesc->descriptorType != typeNull &&
  218.          IsntNil( theAEDesc->dataHandle ) &&
  219.          DebugLeaks_ItemIsRemembered( theAEDesc->dataHandle ))
  220.         {
  221.         ForgetItem( theAEDesc->dataHandle );
  222.         }
  223.     }
  224.  
  225.  
  226.  
  227. /*————————————————————————————————————————————————————————————————————————————————————————
  228.     An object has been allocated. Remember it.
  229.     
  230.     Override operator new() so you can remember objects.
  231. ————————————————————————————————————————————————————————————————————————————————————————*/
  232.     void
  233. DebugLeaks_RememberObject(
  234.     void    *object,
  235.     UInt32    size)
  236.     {
  237.     // initialize a RememberedItem appropriately and add it to list
  238.     }
  239.  
  240.  
  241. /*————————————————————————————————————————————————————————————————————————————————————————
  242.     An object has been deallocated. Forget it.
  243.     
  244.     Note: you will need to override operator delete() so you can call this routine.
  245. ————————————————————————————————————————————————————————————————————————————————————————*/
  246.     void
  247. DebugLeaks_ForgetObject( void *object )
  248.     {
  249.     ForgetItem( object );
  250.     }
  251.     
  252.     
  253.  
  254. /*————————————————————————————————————————————————————————————————————————————————————————
  255.     Return true if an item is remembered.
  256. ————————————————————————————————————————————————————————————————————————————————————————*/
  257.     Boolean
  258. DebugLeaks_ItemIsRemembered( const void    *handleOrPtr )
  259. {
  260.     return( false );
  261. }
  262.  
  263.  
  264. /*————————————————————————————————————————————————————————————————————————————————————————
  265.     A Handle is being disposed of via DisposeHandle().
  266.     Verify this is the proper way to dispose of it, as opposed to a more specific routine.
  267.     
  268.     For example, DisposeHandle should not be called on an IconSuiteHandle.
  269. ————————————————————————————————————————————————————————————————————————————————————————*/
  270.     void
  271. DebugLeaks_DisposingHandle( Handle    theHandle)
  272.     {
  273.     }
  274.  
  275.  
  276.  
  277. /*————————————————————————————————————————————————————————————————————————————————————————
  278.     A Ptr is being disposed of via DisposePtr().
  279.     Verify this is the proper way to dispose of it, as opposed to a more specific routine.
  280.     
  281.     For example, DisposePtr should not be called on a WindowPtr.
  282. ————————————————————————————————————————————————————————————————————————————————————————*/
  283.     void
  284. DebugLeaks_DisposingPtr( Ptr thePtr)
  285.     {
  286.     }
  287.  
  288.  
  289.  
  290. /*————————————————————————————————————————————————————————————————————————————————————————
  291.     Ignore this item (Ptr, Handle or object).  It will not be reported as a leak.
  292.     However, the item should remain in the list of remembered items until it has
  293.     been disposed. This allows stricter assertions in some cases (e.g. an attempt to
  294.     dispose of it twice).
  295. ————————————————————————————————————————————————————————————————————————————————————————*/
  296.     void
  297. DebugLeaks_IgnoreItem( const void *mem)
  298.     {
  299.     }
  300.  
  301.  
  302.  
  303. #if PRAGMA_MARK_SUPPORTED
  304. #pragma mark -
  305. #pragma mark --- General Public Use ---
  306. #endif
  307.  
  308.  
  309. /*————————————————————————————————————————————————————————————————————————————————————————
  310.     Initialize the leaks code. Call this before using any leaks routines.
  311.     
  312.     Calls to Leaks services before initialization are ignored.
  313. ————————————————————————————————————————————————————————————————————————————————————————*/
  314.     void
  315. DebugLeaks_Init(void)
  316.     {
  317.     }
  318.  
  319.  
  320.  
  321. /*————————————————————————————————————————————————————————————————————————————————————————
  322.     After calling this calls to Leaks services are ignored.
  323. ————————————————————————————————————————————————————————————————————————————————————————*/
  324.     void
  325. DebugLeaks_Dispose(void)
  326.     {
  327.     }
  328.  
  329.  
  330. /*————————————————————————————————————————————————————————————————————————————————————————
  331.     Allocate memory for a new session and make it the current session.
  332. ————————————————————————————————————————————————————————————————————————————————————————*/
  333.     void
  334. DebugLeaks_StartSession(
  335.     UInt32                maxItemsToTrack,
  336.     ConstStr255Param    sessionName)
  337.     {
  338.     }
  339.  
  340.  
  341. /*————————————————————————————————————————————————————————————————————————————————————————
  342.     Stop remembering leaks, and if there are any leaks, report them. Then dispose
  343.     of the session. The previous session (if any) becomes active.
  344. ————————————————————————————————————————————————————————————————————————————————————————*/
  345.     void
  346. DebugLeaks_StopSession(void)
  347.     {
  348.     }
  349.     
  350.  
  351. /*————————————————————————————————————————————————————————————————————————————————————————
  352.     All subsequent allocations are recorded, but are marked as having occured during
  353.     a suspended session so they won't be considered leaks. If we completely ignored them,
  354.     then we would get complaints later from DebugLeaks_ForgetXXX() routines.
  355.     
  356.     Keep a "suspend counter" which is decremented for each resume call.
  357. ————————————————————————————————————————————————————————————————————————————————————————*/
  358.     void
  359. DebugLeaks_SuspendSession( void )
  360.     {
  361.     }
  362.     
  363.     
  364. /*————————————————————————————————————————————————————————————————————————————————————————
  365.     Back to normal (provided the suspend count becomes 0).
  366. ————————————————————————————————————————————————————————————————————————————————————————*/
  367.     void
  368. DebugLeaks_ResumeSession( void )
  369.     {
  370.     }
  371.     
  372.  
  373.  
  374.  
  375.  
  376.  
  377. #endif // ] USE_DEBUG_LEAKS
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.